﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GnufBase.h"
#include "GnufBaseUtils.h"

class QTreeWidgetItem;
namespace {
    class ItemEventSender;
}
namespace gnuf {
    class Item;
    class Button;
    class DropdownMenu;
    class DropdownMenuEntry;
    class ContextMenu;
    class Tab;
    class TabBar;
    class Toolbar;
    class Button;
    class Text;
    class WorkspaceTabBar;
    class WorkspaceTab;
    class Check;
    class Radio;
    class CheckGroup;
    class List;
    class Slider;
    class TreeNode;
    class TreeBoard;
    class FamilyTypes;
    class WidgetAgent;
    class ColorControl;
    class ButtonEx;
    class DropDownButton;
    class CheckButton;
    class DropDownBoard;
    class SearchBox;
    class TableRow;
    class TagPad;
    class Color;
    class ListWidget;
    class Tag;
    class MatrixButton;
    class Block;
    typedef TreeNode FamilyType;

    class ItemEventDispatcher;
    class GNUF_BASE_EXPORT IItemEventHandler
    {
    public:
        enum class EMouseButton
        {
            eLeftButton,
            eMiddleButton, 
            eRightButton
        };

        virtual void onHovered(Item *, bool hovered, void * qtWidget) {}
        virtual void onClicked(Item *) {}
        // Returns true if the event was recognized, otherwise it returns false.
        // If the recognized event was accepted, any further processing such as 
        // event propagation to the control and other event handler both stop.
        virtual bool onPreClicked(Item *) { return false; }
        virtual bool onKeyDown(
            Item* item, 
            int key, 
            bool isAutoRepeat = false, 
            bool isAltModifier = false, 
            bool isShiftModifier = false, 
            bool isCtrlModifier = false
        ) { return false; }
        virtual void onCheckStatusChanged(CheckButton*) {}
        virtual void onCurrentIndexChanged(DropdownMenu *) {}
        virtual void onCheckStatusChanged(DropdownMenu *, int, bool) {}
        virtual void onCheckStatusChanged(Check*, bool) {}
        virtual void onCheckStatusChanged(Radio*, bool) {}
        virtual void onCheckStatusChanged(CheckGroup*, int, bool) {}
        virtual void onCheckStatusChanged(DropDownBoard* ,const std::vector<bool>&) {}
        virtual void onCurrentIndexChanged(DropdownMenuEntry *) {}
        virtual void onCurrentIndexChanged(ContextMenu *) {}
        virtual void onCurrentIndexChanged(WorkspaceTabBar *) {}
        virtual void onCurrentIndexChanged(TabBar *) {}
        virtual void onCurrentIndexChanged(List*, int) {}
        virtual void onCurrentIndexChanged(DropDownBoard*,int, Item*) {}
        virtual void onTabCloseButtonClicked(Tab *) {}
        virtual bool onDragOff(Tab *) { return false; }
        virtual bool onDragOff(TreeNode *) { return false; }
        virtual void onDrop(TreeNode*) {}
        virtual void onHeightChanged(Toolbar *, int) {}
        virtual void onQtMousePressed(Toolbar *, void *) {}
        virtual void onQtMouseDoubleClicked(Toolbar *, void *) {}
        virtual void onDraggingAndMoving(Toolbar *, int oldGlobalX, int oldGlobalY, int globalX, int globalY) {}
        virtual bool onValidateText(Text *, const std::wstring & undeterminedText, std::wstring * hintIfInvalid) { return true; }
        virtual void onTextChanged(Text *) {}
        virtual void onEditingFinished(Text*){}
        virtual void onValueChanged(Slider *) {}
        virtual void onRangeChanged(Slider*) {}
        virtual void onTreeItemClicked(TreeNode*) {}
        virtual void onTreeItemIconButtonClicked(TreeNode*, int iconIndex) {}
        virtual void onTreeItemHovered(TreeNode*, int iconIndex) {}
        virtual void onTreeItemDbClicked(TreeNode*) {}
        virtual void onTreeItemRButtonClicked(TreeNode*, int x, int y) {}
        virtual void onTreeItemChanged(QTreeWidgetItem *item, int column) {}
        virtual void onTreeItemSelectionChanged(TreeBoard* treeBoard, const std::list<TreeNode*>& selectedItems) {}
        virtual void onAddFamilyType(FamilyType *) {}
        virtual void onEditFamilyType(FamilyType *) {}
        virtual void onCurrentFamilyTypeChanged(FamilyTypes *, FamilyType * oldType, FamilyType * curType) {}
        virtual void onWidgetAgentEvent(WidgetAgent*) {}
        virtual void onTableRowSelectionChanged(WidgetAgent *, void * qtWidget,
            bool selected, const gnuf::Color & selectedBackgroundColor) {}
        virtual bool onDoesApproveOfSwitching(WorkspaceTabBar *, WorkspaceTab *, WorkspaceTab *) { return true; }
        virtual void onColorChanged(ColorControl*) {}
        virtual void onSmartColorEnabled(ColorControl *) {}
        virtual void onSearchFinished(SearchBox*,const std::list<std::wstring>&) {}
        virtual void onSelectChanged(Item*, int, bool) {}
        virtual void onTextChanged(Item*,const std::wstring&) {}
        virtual void onClicked(TableRow*, int buttonIndex) {}
        virtual void onHovered(TableRow*, bool hovered, void * qtWidget,
            int elementIndex /* -1:Caption, 0:Button-0, 1:Button-1, ..., N:Button-N */) {}
        virtual void onTagSelected(TagPad* pTagPad, Tag* tag, bool bSelected) {}
        virtual void onItemPressed(ListWidget *, std::wstring &, int operationType) {}
        virtual void onMatrixButtonClickedAt(MatrixButton*, Point) {};

        virtual void onFocusIn(Item* item) {};
        virtual void onFocusOut(Item* item) {};

        virtual void onClicked(Item*, IItemEventHandler::EMouseButton) {};

        virtual bool onAllowToShow(Item *) const { return true; }

        virtual void onCustomizedInfoSupportedChanged(ColorControl*) {}

        struct ContentChange {
            bool visibility = false;
    };
        virtual void onContentChanged(Item *, const IItemEventHandler::ContentChange &) {}
    private:
        friend class ItemEventDispatcher;
        gcmp::OwnerPtr< gcmp::WeakReferenceable > m_opValidity;
    };

    class ItemEventDispatcher final : public IItemEventHandler, public gcmp::WeakReferenceable
    {
    public:
        ItemEventDispatcher(IItemEventHandler * eventHandler);
        bool isEventHandlerValid() const;

        //
        // Inherits from IItemEventHandler...
        virtual void onHovered(Item * item, bool hovered = false, void * qtWgt = nullptr);
        virtual void onClicked(Item *) override;
        virtual bool onKeyDown(Item * item, int key, bool isAutoRepeat, bool isAltModifier, bool isShiftModifier, bool isCtrlModifier);
        virtual void onCheckStatusChanged(CheckButton*) override;
        virtual void onCurrentIndexChanged(DropdownMenu *) override;
        virtual void onCheckStatusChanged(DropdownMenu *, int, bool) override;
        virtual void onCheckStatusChanged(Check*, bool checked) override;
        virtual void onCheckStatusChanged(Radio*, bool checked) override;
        virtual void onCheckStatusChanged(CheckGroup*, int index, bool checked) override;
        virtual void onCheckStatusChanged(DropDownBoard*, const std::vector<bool>&) override;
        virtual void onCurrentIndexChanged(DropdownMenuEntry *) override;
        virtual void onCurrentIndexChanged(ContextMenu *) override;
        virtual void onCurrentIndexChanged(WorkspaceTabBar *) override;
        virtual void onCurrentIndexChanged(TabBar *) override;
        virtual void onCurrentIndexChanged(DropDownBoard*,int, Item*) override;
        virtual void onTabCloseButtonClicked(Tab *) override;
        virtual bool onDragOff(Tab *) override;
        virtual bool onDragOff(TreeNode*) override;
        virtual void onDrop(TreeNode*) override;
        virtual void onCurrentIndexChanged(List *, int index) override;
        virtual void onHeightChanged(Toolbar *, int height) override;
        virtual void onQtMousePressed(Toolbar *, void * qtEvt) override;
        virtual void onQtMouseDoubleClicked(Toolbar *, void * qtEvt) override;
        virtual void onDraggingAndMoving(Toolbar *, int oldGlobalX, int oldGlobalY, int globalX, int globalY) override;
        virtual bool onValidateText(Text *, const std::wstring & undeterminedText, std::wstring * hintIfInvalid) override;
        virtual void onTextChanged(Text *) override;
        virtual void onEditingFinished(Text*)override;
        virtual void onValueChanged(Slider*) override;
        virtual void onRangeChanged(Slider*) override;
        virtual void onTreeItemClicked(TreeNode *) override;
        virtual void onTreeItemIconButtonClicked(TreeNode *, int iconIndex) override;
        virtual void onTreeItemHovered(TreeNode*, int iconIndex) override;
        virtual void onTreeItemDbClicked(TreeNode *) override;
        virtual void onTreeItemRButtonClicked(TreeNode *, int x, int y) override;
        virtual void onTreeItemChanged(QTreeWidgetItem *item, int column) override;
        virtual void onTreeItemSelectionChanged(TreeBoard* treeBoard, const std::list<TreeNode*>& selectedItems) override;
        virtual void onAddFamilyType(FamilyType *) override;
        virtual void onEditFamilyType(FamilyType *) override;
        virtual void onCurrentFamilyTypeChanged(FamilyTypes *, FamilyType * oldType, FamilyType * curType) override;
        virtual void onWidgetAgentEvent(WidgetAgent *) override;
        virtual void onTableRowSelectionChanged(WidgetAgent *, void * qtWidget,
            bool selected, const gnuf::Color & selectedBackgroundColor) override;
        virtual bool onDoesApproveOfSwitching(WorkspaceTabBar *, WorkspaceTab * oldWorkspaceTab, WorkspaceTab * newWorkspaceTab) override;
        virtual void onColorChanged(ColorControl*) override;
        virtual void onSmartColorEnabled(ColorControl *) override;
        virtual void onSearchFinished(SearchBox*,const std::list<std::wstring>&) override;
        virtual void onSelectChanged(Item*, int,bool) override;
        virtual void onTextChanged(Item*, const std::wstring&) override;
        virtual void onClicked(TableRow*, int buttonIndex) override;
        virtual void onHovered(TableRow*, bool hovered, void * qtWidget,
            int elementIndex /* -1:Caption, 0:Button-0, 1:Button-1, ..., N:Button-N */) override;
        virtual void onTagSelected(TagPad*, Tag*, bool) override;
        virtual void onItemPressed(ListWidget *pListWidget, std::wstring &name, int operationType) override;
        virtual void onMatrixButtonClickedAt(MatrixButton* matrix, Point p);

        virtual void onFocusIn(Item* item) override;
        virtual void onFocusOut(Item* item) override;

        virtual void onClicked(Item*, IItemEventHandler::EMouseButton) override;

        virtual bool onAllowToShow(Item *) const override;
        virtual void onContentChanged(Item *, const IItemEventHandler::ContentChange &) override;

        virtual void onCustomizedInfoSupportedChanged(ColorControl*) override;
    private:
        struct {
            IItemEventHandler *                      m_ptr = nullptr;
            gcmp::WeakPtr< gcmp::WeakReferenceable > m_wpValidity;

            bool                         isValid() const { return m_wpValidity.IsValid(); }
            const IItemEventHandler *        get() const { return (isValid() ? m_ptr : nullptr); }
                  IItemEventHandler *        get()       { return (isValid() ? m_ptr : nullptr); }
            const IItemEventHandler * operator->() const { return get(); }
                  IItemEventHandler * operator->()       { return get(); }
            operator const IItemEventHandler *  () const { return get(); }
        } m_eventHandler;
    };

    class GNUF_BASE_EXPORT ItemEvent final
    {
    public:
        static ItemEvent * current();
        const Item * sender() const;
        const std::string & whatsThis() const { return m_whatsThis; }
        bool accepted() const { return m_accepted; }
        void setAccepted() { m_accepted = true; }
        bool valid() const;
    private:
        friend class ItemEventDispatcher;
        explicit ItemEvent(const ItemEventDispatcher *, Item *, const char *);
        ~ItemEvent();

        gcmp::WeakPtr<ItemEventDispatcher> m_wpDispatcher;
        gcmp::OwnerPtr<::ItemEventSender> m_sender;
        const std::string m_whatsThis;
        bool m_accepted;
    };
}
